昨天我們簡單看了基礎型別(三個原始值、陣列、function),跟一些使用方法,今天繼續看TypeScript讓你開發更便捷的地方!
除了昨天提到的,你可以設定參數跟回傳值的型別外,當你已經設定好參數的型別,並且要在函式內使用該參數的方法或屬性時,編輯器會在你打錯字、取用錯誤的屬性時提醒你!
let people: string[] = ["John", "Ted", "Allen"]
people.forEach(name=>{
console.log(name.touppercase())
//Property 'touppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
})
function sayHi(person:{name: string, age: number}){
console.log(person.address)
//Property 'address' does not exist on type '{ name: string; age: number; }'.
}
第一個例子中,因為TypeScript知道我們的people
都是字串,所以對這陣列使用forEach
後,他也會知道裡面的name
是什麼型別,就會幫我們去判斷,我們在name
後綴的屬性/方法,是否真實存在,像這邊,我們拼錯了toUpperCase(),這個錯誤在我們一打完字就被發現了,不會等到執行時才在console看到name.touppercase is not a function
,非常方便。
旁邊的燈泡甚至會直接問你:要不要幫你改成toUpperCase?
第二個例子sayHi
當中,由於我們設定的參數person
物件,並沒有一個屬性叫做address,所以TypeScript也很明確的噴出錯誤。跟昨天的processInput
例子類似,當我們輸入到person.
之後,TypeScript會提示你:「person
只有age
跟name
這兩個屬性, 且age
的型別是數字」,這樣一來,要是person
的屬性有很多、或者說屬性名稱沒這麼好記,你就不用特地回去翻找你的屬性的確切拼法是什麼了,可以省下一些時間。
先前的例子裡,我們都只為變數或參數設定了"單一種"型別,但我們也有可能想讓某個值同時接納兩種(或以上)的型別。
function sayHi2(person: string | number){
console.log(person)
}
sayHi2("John")
sayHi2(9527) //知道這個的應該有點年紀了...
//上述這兩行都不會有錯
sayHi2({name:"Ronald"})
//Argument of type '{ name: any; Ronald: any; }' is not assignable to parameter of type 'string | number'.
//應該滿明顯的,我們就只接受字串跟數字當作參數的型別
這樣做好像很方便,我們可以不侷限於一種型別。但,上述例子中使用了型別聯集,不代表你可以對person
同時使用"所有"string跟number的方法。
function sayHi2(person: string | number){
console.log(person.toUpperCase())
}
//Property 'toUpperCase' does not exist on type 'string | number'. Property 'toUpperCase' does not exist on type 'number'.
//如果這邊我們用的是person.toString()就不會報錯,因為不管是字串或數字,都有.toString方法
意思就是,你必須使用”同時存在於字串與數字的方法”,所以名義上叫聯集,從功能上來看反而算是”交集”。
所以,要處理這個錯誤,你就必須在函式內對person
型別進行一層型別防衛(Type guard):
function sayHi2(person: string | number){
if(typeof person ==="string"){
console.log(person.toUpperCase())
//這樣就不會噴錯了
}
}
再來講今天最後一個觀念:型別別名(Type alias)
今天一直在範例中看到(person: string | number)
,但要是這個型別判斷需要一直在專案中出現,一直重複打字或複製貼上,對於工程師來講都是很不明智的一件事。所以,我們可以特定為這組型別命名,方便我們後續使用。
type Person = string | number
function sayHi3(person: Person){
if(typeof person ==="string"){
console.log(person.toUpperCase())
}
}
function sayHi4(person: Person){
//進行不同操作
}
如此就能省去不少時間,而且在語意上因為有了別名,我們對於這個參數又有更多的瞭解了!(雖然這裡我取名叫Person,但要是專案內有Customer、Staff、Supervisor等身份作為型別別名,就會更有意義了lol)
今天先講這些,明天再繼續聊TypeScript的基礎型別及功能!
明天會提到使用型別聯集時,也會搭配使用的東西:型別斷言(Type assertion)